package niotest;

import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
import java.util.Date;
import java.util.Iterator;
import java.util.Set;

import netmsg.ProtocolMessage;

public class TimeService {

	private void acceptConnections(int port) throws Exception {
		// 打开一个 Selector
		Selector selector = SelectorProvider.provider().openSelector();

		// 创建一个 ServerSocketChannel ，这是一个 SelectableChannel 的子类
		ServerSocketChannel ssc = ServerSocketChannel.open();
		// 将其设为 non-blocking 状态，这样才能进行非阻塞 IO 操作
		ssc.configureBlocking(false);

		// 给 ServerSocketChannel 对应的 socket 绑定 IP 和端口
		InetSocketAddress isa = new InetSocketAddress("127.0.0.1", port);
		ssc.socket().bind(isa);

		// 将 ServerSocketChannel 注册到 Selector 上，返回对应的 SelectionKey
		SelectionKey acceptKey = ssc.register(selector, SelectionKey.OP_ACCEPT);

		SelectionKey readKey = null;
		SelectionKey writeKey = null;
		SelectionKey connectKey = null;

		
		// 用 select() 函数来监控注册在 Selector 上的 SelectableChannel
		// 返回值代表了有多少 channel 可以进行 IO 操作 (ready for IO)
		while (selector.select()>0) {
			System.out.println(selector.select());
			// selectedKeys() 返回一个 SelectionKey 的集合，
			// 其中每个 SelectionKey 代表了一个可以进行 IO 操作的 channel 。
			// 一个 ServerSocketChannel 可以进行 IO 操作意味着有新的 TCP 连接连入了
			Set<SelectionKey> readyKeys = selector.selectedKeys();

			if (readyKeys.size() > 0) {
				System.out.println(readyKeys);
			}

			Iterator<SelectionKey> i = readyKeys.iterator();

			while (i.hasNext()) {
				SelectionKey sk = (SelectionKey) i.next();

				// 需要将处理过的 key 从 selectedKeys 这个集合中删除
				i.remove();
				if (sk == acceptKey) {
					System.out.println("##accept.");
					// 从 SelectionKey 得到对应的 channel
					ServerSocketChannel nextReady = (ServerSocketChannel) sk
							.channel();
					// 接受新的 TCP 连接
					Socket s = nextReady.accept().socket();

					SocketChannel sc = s.getChannel();
					sc.configureBlocking(false);
					readKey = sc.register(selector, SelectionKey.OP_READ);
					// writeKey = sc.register(selector, SelectionKey.OP_WRITE);
					// connectKey = sc.register(selector,
					// SelectionKey.OP_CONNECT);

					// 把当前的时间写到这个新的 TCP 连接中
					ByteBuffer bb = ByteBuffer.allocateDirect(1024);
					Date now = new Date();
					String nowStr = now.toString();
					bb.putInt(ProtocolMessage.COMMAND_SEND_MSG);
					byte[] a = "server#1#".getBytes();
					byte[] b = nowStr.getBytes();
					bb.putInt(a.length + b.length);
					bb.put(a);
					bb.put(b);
					bb.flip();
					sc.write(bb);

					// 关闭连接
					// out.close();
				} else if (sk == readKey) {
					System.out.println("##read.");
					SocketChannel sc= (SocketChannel)sk.channel();
					ByteBuffer bb = ByteBuffer.allocateDirect(1024);
					sc.read(bb);
					bb.flip();
					System.out.println(bb);
				} else if (sk == writeKey) {
					System.out.println("##write.");
				} else if (sk == connectKey) {
					System.out.println("##connect.");
				}else{
					System.out.println("##what?");
				}
			}
		}
	}

	public static void main(String[] args) throws Exception {
		TimeService ts = new TimeService();
		ts.acceptConnections(9977);
	}

}
